package com.mkx.domain.vo;

import lombok.Getter;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * 密码值对象
 * 封装密码的加密和验证逻辑
 */
@Getter
public class Password {
    
    private final String hash;
    private final String salt;
    
    /**
     * 私有构造函数
     */
    private Password(String hash, String salt) {
        this.hash = hash;
        this.salt = salt;
    }
    
    /**
     * 创建新密码（自动生成盐值并加密）
     */
    public static Password create(String plainPassword) {
        if (plainPassword == null || plainPassword.length() < 6) {
            throw new IllegalArgumentException("密码长度不能少于6位");
        }
        
        // 生成随机盐值
        String salt = generateSalt();
        
        // 计算密码哈希
        String hash = hashPassword(plainPassword, salt);
        
        return new Password(hash, salt);
    }
    
    /**
     * 从已有哈希和盐值重建密码对象
     */
    public static Password fromExisting(String hash, String salt) {
        if (hash == null || salt == null) {
            throw new IllegalArgumentException("密码哈希和盐值不能为空");
        }
        return new Password(hash, salt);
    }
    
    /**
     * 验证密码
     */
    public boolean matches(String plainPassword) {
        if (plainPassword == null) {
            return false;
        }
        String computedHash = hashPassword(plainPassword, salt);
        return hash.equals(computedHash);
    }
    
    /**
     * 生成随机盐值
     */
    private static String generateSalt() {
        SecureRandom random = new SecureRandom();
        byte[] saltBytes = new byte[16];
        random.nextBytes(saltBytes);
        return Base64.getEncoder().encodeToString(saltBytes);
    }
    
    /**
     * 哈希密码
     */
    private static String hashPassword(String password, String salt) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(salt.getBytes());
            byte[] hashedBytes = md.digest(password.getBytes());
            return Base64.getEncoder().encodeToString(hashedBytes);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("密码加密失败", e);
        }
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Password password = (Password) obj;
        return hash.equals(password.hash) && salt.equals(password.salt);
    }
    
    @Override
    public int hashCode() {
        int result = hash.hashCode();
        result = 31 * result + salt.hashCode();
        return result;
    }
}